/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc7_tti_rxh.c                                 */
/*  NOTE      =                                                    */
/*  DATE      = 2014/11/21 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frcomm.h"
#include "frstr.h"
#include "frmem.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "../ttc8/ora_ttc8_tti_rxd.h"
#include "ora_ttc7_tti_rxh.h"


/*******************************************************************************
*  FUNC     :  对应于 9i的 oracle.jdbc.ttc7.v8TTIrxh的 public void unmarshal() 方法
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc7_tti_rxh_unmarshal(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , Sql_statement *p_st_stmt)
{
    ORA_PRINT_INFO("ora_ttc7_tti_rxh_unmarshal...\n");
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;
    short s_tmp = 0;
    short s_rxhflg = 0;
    int i_tmp = 0;
    long long ll_tmp = 0LL;
    int i_byte_num = 0;
    int i_numRqsts = 0;
    int i_iterNum = 0;
    char *p_tmp = NULL;
    int i_tmp_len = 0;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_rxhflg) != FR_SUCC) // flags
        goto error;

    if (p_st_sess->i_ttc7_rxhrqsts == FR_YES) // p_st_sess->s_ora_version >= 8030
    {
        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_numRqsts) != FR_SUCC) // numRqsts
            goto error;
    }
    else
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC) // numRqsts
            goto error;
        i_numRqsts = s_tmp;
    }

    if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_iterNum) != FR_SUCC) // iterNum
        goto error;

    if (s_rxhflg == 0x02 || s_rxhflg == 0x05 || s_rxhflg == 0x1a || s_rxhflg == 0x22)
    {
        ORA_PRINT_DBG("i_iterNum = i_numRqsts = %d\n", i_numRqsts);
        i_iterNum = i_numRqsts;
    }
    else if (s_rxhflg == 0x00 || s_rxhflg == 0x01)
    {
        ORA_PRINT_DBG("i_iterNum = %d\n", i_iterNum);
    }
    else
    {
        ORA_PRINT_DBG("i_iterNum = 0\n");
        i_iterNum = 0;
    }

    frdb_set_column_nums(p_st_stmt, i_iterNum);

    if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // numItersThisTime
        goto error;

    if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC) // uacBufLength
        goto error;
    if (p_st_sess->i_use_special_field == FR_NO && i_tmp > 0)
        goto error;

    if (p_st_sess->i_use_special_field == FR_YES)
    {
#if APM_ORA_DBG
        int i_pos_start = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
#endif
        // 0x02 0x05 0x0a 0x1a 0x22
        if (s_rxhflg == 0x02 || s_rxhflg == 0x05 || s_rxhflg == 0x0a || s_rxhflg == 0x1a || s_rxhflg == 0x22)
        {
            if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                goto error;
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC)
                goto error;
            i_byte_num = (int) ll_tmp;
            if (i_byte_num > 0LL)
            {
                if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                    goto error;
            }
            if (p_st_sess->s_tns_version >= 313)
            {
                if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                    goto error;
            }
        }
        else
        {
            if (ora_mar_skip(p_st_ora_packet, 8) != FR_SUCC)
                goto error;
            if (p_st_sess->s_tns_version >= 313)
            {
                if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
                    goto error;
            }
            if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_byte_num) != FR_SUCC) // bitVectors的个数
                goto error;
            if (ora_mar_skip(p_st_ora_packet, 10) != FR_SUCC)
                goto error;
            if (p_st_sess->c_ttc_version >= 4 && p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8)
            {
                if (ora_mar_skip(p_st_ora_packet, 16) != FR_SUCC)
                    goto error;
            }
        }
#if APM_ORA_DBG
        ORA_PRINT_DBG("skip %d bytes after uacBufLength\n", bytebuff_getPosition(p_st_ora_packet->p_st_packet) - i_pos_start);
#endif
    }
    else // 测试到这个案例时加入的以下部分 ./apm -n -t 1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/aix/4_sqlplus_192.168.18.166_9.2.0.1.0_z_windows_2_192.168.18.228_11.2.0.1.0_w_sqe_off.pcap
    {
        // 测试到这个案例时加入以下这个判断 ./apm -n -t 1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/9i/call_procedure.pcap
        ORA_PRINT_DBG("i_iov_processed_flag:[%s]\n", FR_YESNO2STR(p_st_curr_sess->i_iov_processed_flag));
        if (p_st_sess->i_use_oci == FR_YES && p_st_curr_sess->i_iov_processed_flag == FR_NO)
        {
            if (ora_mar_unmarshalDALC(p_st_sess, p_st_ora_packet, &p_tmp, &i_tmp_len) == FR_SUCC) // bitVector
            {
                if (ora_ttc8_tti_rxd_readBitVector(p_st_conn, p_tmp, i_tmp_len) != FR_SUCC)
                {
                    ora_free((void **) &p_tmp);
                    goto error;
                }
                ora_free((void **) &p_tmp);
            }
            else
                goto error;

            if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC)
                goto error;
        }
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}
